//============================================================================
// Name        : CapaN-Distribuidos.cpp
// Author      : 
// Version     :
// Copyright   : 
//============================================================================

#include <iostream>
#include <cstring>
#include "../IPC/SizedMessageQueue.h"
#include "../middleware/MiddlewareCommon.h"
#include "../channel_common/ChannelInterface.h"
#include "../common/Argv.h"
#include "../logger/logger.h"
#include "../common/StringUtils.h"
#include "../common/IPCUids.h"
#include "IPC/DistributedIPCLauncher.h"
#include "../CapaComunicacion/APICapaComunicacion.h"

using namespace std;
using namespace channel;

/*
 *  Componente de capa N : Emisor de Mensajes de MQueue
 *
 *	- Lee en una cola en particular
 *	- Saca un nuevo mensaje M
 *	- Construye el payload de la capa de servicios distribuidos:
 *		- Size = sizeof(t_mensaje)
 *		- Id cola destino = Id de la que estoy leyendo
 *		- Mtype = mtype
 *		- Mensaje = M
 *
 *	- Envia a la capa de comunicaciones el paquete de capa N, dirigido al idAgenteDestino.
 */
int main(int argc, char* argv[]) {
	Argv args(argv);
	CLogger::create("Emisor mensajes", true);

	if (args.getArgc() < 5) {
		cout << "Uso: ./emisor nombreAgenteDestino UuidColaDestino MtypeColaDestino SizeMensaje" << endl;
		CLogger::log("Parámetros incorrectos", LogLevelEnum::FATAL);
		exit(1);
	}

	/* Obtenemos parametros */
	std::string nombreAgenteDestino = args.getArg(2);
	int uidColaDestino = args.getArgAsInt(3);
	int mtype = args.getArgAsInt(4);
	int size = args.getArgAsInt(5);

	/* Debug: imprimimos parametros */
	CLogger::log("Agente destino" + nombreAgenteDestino);
	CLogger::log("Id de cola destino" +StringUtils::itos(uidColaDestino));
	CLogger::log("Mtype " + StringUtils::itos(mtype));
	CLogger::log("Size del mensaje " + StringUtils::itos(size));

	/* Datos obtenidos por uidColaDestino */
	std::string file = IPCUids::getFile(uidColaDestino, false);
	int charKey = IPCUids::getKey(uidColaDestino);
	if (IPCUids::error()) {
		CLogger::log("Error al obtener datos del uid, chequee que exista el uid "+ StringUtils::itos(uidColaDestino)+" por favor.", LogLevelEnum::FATAL);
		exit(1);
	}

	bool conexionTerminada = false;
	while(!conexionTerminada) {

		/* Datos a obtener de la cola */
		char data[TAM_PAYLOAD_MQ];
		memset(data, 0, TAM_PAYLOAD_MQ);

		CLogger::log("Esperando mensaje de la aplicacion, para emitir a la capa de comunicaciones. ", LogLevelEnum::INFO);

		/*  Cola especifica del proceso, se lee por size */
		ipc::SizedMessageQueue cola = ipc::SizedMessageQueue::create(file,charKey);
		cola.get(mtype, data, size);

		/* Armamos protocolo de capa N */
		PayloadServicioMensajes payloadServicioMensajes;
		payloadServicioMensajes.mtype = mtype;//mtype del que yo leo
		payloadServicioMensajes.size = size;
		memcpy(payloadServicioMensajes.data, data, size);

		PDUServicioMensajes pduMensajes;
		pduMensajes.UidColaDestino = uidColaDestino;
		pduMensajes.size = TAM_PDU_MQ;
		pduMensajes.payloadMq = payloadServicioMensajes;

		PDUCapaServicios pduServicios;
		pduServicios.tipo = MTYPE_CAPAN_MENSAJES;
		pduServicios.size = TAM_PAYLOAD_CAPAN;
		pduServicios.payload = (PayloadCapaServicios) pduMensajes;

		char pduserializado[TAM_PDU_CAPAN];
		memcpy((void*)pduserializado,(const void*)&pduServicios,TAM_PDU_CAPAN);

		ChannelInterface channel(ChannelInterface::SENDER);
		channel.send(nombreAgenteDestino, pduserializado,TAM_PDU_CAPAN);
	}
	return 0;
}
